package cn.yx.common.security.webflux.handler;

import cn.yx.common.core.enums.ResponseCodeEnum;
import cn.yx.common.core.pojo.ResponseVo;
import cn.yx.common.security.webflux.sms.SmsCodeErrorException;
import cn.yx.common.security.webflux.sms.SmsCodeExpirationException;
import cn.yx.common.webflux.util.WebFluxUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

/**
 * <p>用户认证失败处理器。
 * 用户认证失败，需要返回错误消息</p>
 *
 * @author Wgssmart
 */
@Component
@Slf4j
public class CustomAuthenticationFailureHandler implements ServerAuthenticationFailureHandler {

    @Override
    public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException exception) {
        String msg = ResponseCodeEnum.AUTHENTICATION_ERROR.getMessage();
        if (exception instanceof DisabledException) {
            msg = "cn.yx.common.security.userNotEnabled";
        } else if (exception instanceof UsernameNotFoundException) {
            msg = "cn.yx.common.security.userNotExist";
        } else if (exception instanceof BadCredentialsException) {
            msg = "cn.yx.common.security.badCredential";
        } else if (exception instanceof LockedException) {
            msg = "cn.yx.common.security.userLocked";
        } else if (exception instanceof SmsCodeExpirationException) {
            msg = exception.getMessage();
        } else if (exception instanceof SmsCodeErrorException) {
            msg = exception.getMessage();
        }
        log.error("authentication failure: {}, {}", exception.getMessage(), msg);
        ServerHttpResponse response = webFilterExchange.getExchange().getResponse();
        return WebFluxUtil.write(response, ResponseVo.authenticationError(msg));
    }
}
